import Phaser from 'phaser';
import {Plugin as NineSlicePlugin} from 'phaser3-nineslice';
import {ProgressBar} from "phaser3-progressbar";
import {randomInt} from './utils/num';
import setting_btn_img from './assets/icons/02vdWAo1p9.png';
import bg_img from './assets/imgs/0VxYQB0RmW.jpg';
import time_bar from './assets/imgs/V26uIS1L0z.png';
import slice_img_dlg_bg from './assets/imgs/FZuFAWjohE.png';
import sprite_btn_0 from './assets/imgs/dolDz3NYPM.png';
import bf0Png from './assets/fonts/bitmap/desyrel.png';
import bf0Xml from './assets/fonts/bitmap/desyrel.xml';
import bf1Png from './assets/fonts/bitmap/nokia.png';
import bf1Xml from './assets/fonts/bitmap/nokia.xml';
import cn_common_png from './assets/fonts/bitmap/cn_common_0.png';
import cn_common_xml from './assets/fonts/bitmap/cn_common.xml';
import fx_mixdown_json from './assets/audio/SoundEffects/fx_mixdown.json';
import fx_mixdown_mp3 from './assets/audio/SoundEffects/fx_mixdown.mp3';
import fx_mixdown_ogg from './assets/audio/SoundEffects/fx_mixdown.ogg';
import win_sound_mp3 from './assets/audio/win.mp3';

let num_arr = [];
let level_num = 0;
const level_data = [3, 4, 5, 6, 7];

let row_num = 3;
let col_num = 3;
let max_num = row_num * col_num;
const win_width = window.innerWidth;
const win_height = window.innerHeight;

let stage_width = 960;
let stage_height = 540;

let grid_width = stage_height / col_num;
let grid_height = stage_height / row_num;
const grid_space = 8;
const margin_h_rate = 0.5;
const margin_v_rate = 0.3;
let margin_fix = (stage_width - stage_height) * margin_h_rate;

let num_card_map = {};
let start_mts = 0;
let direction = 1;
let consume_sec = 0;
const dlg_ml = 30;
let dlg_mt = 60;

function initSize() {
    stage_width = win_width;
    stage_height = win_height;
    grid_width = stage_width / col_num;
    grid_height = stage_width / row_num;
    margin_fix = (stage_height - stage_width) * margin_v_rate;
    direction = 2;
}

if (win_width < win_height) {
    initSize();
    dlg_mt = 120;
}

const stage_width_half = stage_width / 2;
const stage_height_half = stage_height / 2

let rect_width = grid_width - grid_space;
let rect_height = grid_height - grid_space;
let current_num = 1;
let bg_layer;
let bottom_layer;
let menu_layer;
let main_layer;
let sec_text;
let timer_handler;
let sec_text_width;
let game_state_dlg;
let game_state_dlg_visible = false;
let dlg_bg;
let replay_btn;
let card_group;
let level_result;

const init_num_arr = () => {
    current_num = 1;
    num_card_map = {};
    const nums = [];
    num_arr = [];
    for (let i = 1; i <= max_num; i++) {
        nums.push(i);
    }
    for (let j = 1; j <= max_num; j++) {
        const n = randomInt(0, max_num - j);
        const v = nums.splice(n, 1);
        num_arr.push(v);
    }
}

class MyGame extends Phaser.Scene {
    constructor(config) {
        super(config);
    }

    preload() {
        const barW = this.sys.canvas.width - 30;
        this.progressBar = new ProgressBar(this, {
            width: barW,
            centerX: barW / 2 + 15,
            centerY: this.sys.canvas.height / 2,
            barRadius: 10,
            paddingH: 10,
            paddingV: 10,
            boxStrokeAlpha: 0.5,
            barFillAlpha: 0.5
        });

        this.load.on('progress', (value) => {
            this.progressBar.update(value);
        });

        this.load.on('complete', () => {
            this.progressBar.destroy();
        });

        this.load.bitmapFont('desyrel', bf0Png, bf0Xml);
        this.load.bitmapFont('nokia', bf1Png, bf1Xml);
        this.load.bitmapFont('cn_common_fnt', cn_common_png, cn_common_xml);
        this.load.image('bg_img', bg_img);
        this.load.image('setting_btn', setting_btn_img);
        this.load.spritesheet('replay_btn', sprite_btn_0, {frameWidth: 150, frameHeight: 60});
        this.load.image('time_bar', time_bar);
        this.load.image('kenny', slice_img_dlg_bg);
        this.load.audioSprite('sfx', fx_mixdown_json, [
            fx_mixdown_mp3,
            fx_mixdown_ogg
        ]);
        this.load.audio('win_sound', [
            win_sound_mp3
        ]);
    }

    create() {
        bg_layer = this.add.layer();
        bottom_layer = this.add.layer();
        main_layer = this.add.layer();
        menu_layer = this.add.layer();
        card_group = this.add.group();

        const bg = this.add.image(stage_width_half, stage_height_half, 'bg_img');
        let scaleX = win_width / bg.width;
        let scaleY = win_height / bg.height;
        let scale = Math.max(scaleX, scaleY);
        bg.setScale(scale).setScrollFactor(0);

        const bg_mask = this.add.graphics();
        bg_mask.fillStyle(0x000680, 0.5);
        bg_mask.fillRoundedRect(0, 0, win_width, win_height, 0);

        bg_layer.add(bg);
        bg_layer.add(bg_mask);
        bottom_layer.add(this.add.image(88, 34, 'time_bar'));
        sec_text = this.add.dynamicBitmapText(80, 24, 'nokia', '0.0"', 20);
        sec_text_width = sec_text.width;
        sec_text.setX(56 + (105 - sec_text_width) / 2);

        const setting_btn_x = win_width - 32;
        const setting_btn = this.add.image(setting_btn_x, 32, 'setting_btn');
        setting_btn.name = 'setting_btn';
        setting_btn.displayWidth = 32;
        setting_btn.displayHeight = 32;
        setting_btn.setInteractive();
        setting_btn.on('clicked', this.handleSetting, this);

        this.sound.add('win_sound');

        // const num_cards = this.add.group({ key: 'num_card', frame: 0, repeat: 13, setXY: { x: 32, y: 32, stepX: 40 } });
        // Phaser.Actions.GridAlign(group.getChildren(), {
        //     width: 10,
        //     height: 10,
        //     cellWidth: 32,
        //     cellHeight: 32,
        //     x: 100,
        //     y: 100
        // });

        game_state_dlg = this.add.group();
        const dlg_width = stage_width - 2 * dlg_ml;
        const dlg_height = 400;
        console.log(dlg_mt);
        dlg_bg = this.add.nineslice(
            dlg_ml,
            dlg_mt,
            dlg_width,
            dlg_height,
            'kenny',
            [210, 36, 36]
        );
        game_state_dlg.add(dlg_bg);
        menu_layer.add(dlg_bg);
        const replay_btn_x = stage_width_half;
        const replay_btn_y = dlg_mt + dlg_height - 75;
        // const replay_btn = this.add.image(replay_btn_x, replay_btn_y, 'replay_btn');
        replay_btn = this.add.image(replay_btn_x, replay_btn_y, 'replay_btn', 1).setInteractive();
        replay_btn.name = 'sprite_btn_0';
        const replay_label_style = {
            font: '18px "微软雅黑"',
            fontWeight: 'bold',
            fill: '#000000'
        };
        const replay_label = this.add.text(replay_btn_x, replay_btn_y - 3, '再来一局', replay_label_style).setOrigin(0.5);

        const success_label_x = stage_width_half;
        const success_label_y = dlg_mt + 50;
        const success_label = this.add.dynamicBitmapText(success_label_x, success_label_y, 'cn_common_fnt', '恭喜通关', 30).setOrigin(0.5);

        menu_layer.add(replay_btn);
        game_state_dlg.add(replay_btn);
        game_state_dlg.add(replay_label);
        game_state_dlg.add(success_label);

        game_state_dlg.setVisible(game_state_dlg_visible);

        this.draw_num_card();

        this.input.on('pointerdown', this.markNumCard, this);
        // down -> over -> up -> out
        this.input.on('gameobjectdown', (pointer, gameObject) => {
            if (gameObject.name === 'sprite_btn_0') {
                gameObject.frame = gameObject.scene.textures.getFrame('replay_btn', 2);
            }
        }, this);
        this.input.on('gameobjectover', (pointer, gameObject) => {
            if (gameObject.name === 'sprite_btn_0') {
                gameObject.frame = gameObject.scene.textures.getFrame('replay_btn', 0);
            }
        }, this);
        this.input.on('gameobjectout', (pointer, gameObject) => {
            if (gameObject.name === 'sprite_btn_0') {
                gameObject.frame = gameObject.scene.textures.getFrame('replay_btn', 1);
                this.toggle_game_state_dialog();
                level_num++;
                const max_level = level_data.length;
                if (level_num >= max_level) {
                    level_num = 0
                }
                row_num = col_num = level_data[level_num];
                max_num = row_num * col_num;
                grid_width = stage_height / col_num;
                grid_height = stage_height / row_num;
                margin_fix = (stage_width - stage_height) * margin_h_rate;
                num_card_map = {};
                start_mts = Date.now();
                sec_text.setText('0.0"');
                direction = 1;
                if (win_width < win_height) {
                    initSize();
                }
                rect_width = grid_width - grid_space;
                rect_height = grid_height - grid_space;
                this.draw_num_card();
            }
        }, this);
        this.input.on('gameobjectup', (pointer, gameObject) => {
            if (gameObject.name === 'sprite_btn_0') {
                gameObject.frame = gameObject.scene.textures.getFrame('replay_btn', 1);
            } else {
                gameObject.emit('clicked', gameObject);
            }
        }, this);

        // const modal = new Modal(this);
        // modal.create();
    }

    draw_num_card() {
        card_group.clear(true, true);
        init_num_arr();
        for (let i = 0; i < row_num; i++) {
            for (let j = 0; j < col_num; j++) {
                const graphics = this.add.graphics();
                card_group.add(graphics);
                bottom_layer.add(graphics);
                graphics.fillStyle(0xffffff, 0.7);
                const font_size = rect_width * 0.6;
                let x = j * grid_width + grid_space / 2;
                let y = i * grid_height + grid_space / 2;
                if (direction === 1) {
                    x += margin_fix;
                } else {
                    y += margin_fix;
                }
                graphics.fillRoundedRect(x, y, rect_width, rect_height, 5);
                const n = i * col_num + j;
                const num = num_arr[n];
                const bitmap_text = this.add.dynamicBitmapText(x, y, 'desyrel', num.toString(), font_size);
                card_group.add(bitmap_text);
                main_layer.add(bitmap_text);
                bitmap_text.setX(x + rect_width / 2 - bitmap_text.width / 2);
                bitmap_text.setY(y + rect_height / 2 - bitmap_text.height / 2);
                num_card_map[num] = {
                    x,
                    y,
                    checked: 0,
                    graphics
                };
            }
        }
    }

    start_timer() {
        start_mts = Date.now();
        timer_handler = setInterval(() => {
            const mts = Date.now();
            consume_sec = ((mts - start_mts) / 1000).toFixed(1);
            sec_text.setText(consume_sec + '"');
            if (sec_text.width !== sec_text_width) {
                sec_text_width = sec_text.width;
                sec_text.setX(56 + (105 - sec_text_width) / 2);
            }
        }, 100);
    }

    stage_completed() {
        this.stop_timer();
        if (level_result && level_result['obj']) {
            level_result['obj'].destroy();
        }
        level_result = {};
        const level_result_x = stage_width_half;
        const level_result_y = dlg_mt + 150;
        const label_result_style = {
            font: '18px "微软雅黑"',
            fontWeight: 'bold',
            fill: '#333333',
            stroke: '#23238e',
            strokeThickness: 2,
        };
        level_result['obj'] = this.add.text(level_result_x, level_result_y, `成绩:  ${consume_sec} 秒`, label_result_style).setOrigin(0.5);
        game_state_dlg.add(level_result['obj']);
        this.toggle_game_state_dialog();
        this.sound.play('win_sound');
    }

    stop_timer() {
        clearInterval(timer_handler);
    }

    toggle_game_state_dialog() {
        game_state_dlg_visible = !game_state_dlg_visible;
        game_state_dlg.setVisible(game_state_dlg_visible);
    }


    markNumCard(pointer) {
        // console.log(pointer.x, pointer.y);
        if (game_state_dlg_visible) {
            return
        }
        for (let num in num_card_map) {
            num = parseInt(num)
            const card_info = num_card_map[num];
            if (pointer.x >= card_info.x && pointer.x <= (card_info.x + grid_width) && pointer.y >= card_info.y && pointer.y <= (card_info.y + grid_height)) {
                if (current_num === 1) {
                    this.start_timer();
                }
                if (current_num === num) {
                    // right
                    card_info.graphics.clear();
                    const graphics = this.add.graphics();
                    card_info.graphics = graphics;
                    card_group.add(graphics);
                    bottom_layer.add(graphics);
                    card_info.graphics.fillStyle(0x00ff00, 0.7);
                    card_info.graphics.fillRoundedRect(card_info.x, card_info.y, rect_width, rect_height, 5);
                    card_info.checked = 1;
                    if (current_num < max_num) {
                        current_num++;
                        this.sound.playAudioSprite('sfx', 'ping');
                    } else if (current_num === max_num) {
                        this.stage_completed();
                    }
                } else {
                    // wrong
                    this.sound.playAudioSprite('sfx', 'meow');
                }
                break;
            }
        }
    }

    handleSetting() {
        this.toggle_game_state_dialog();
    }
}


const config = {
    type: Phaser.AUTO,
    parent: 'phaser-game0',
    backgroundColor: '0x9a9a9a',
    width: stage_width,
    height: stage_height,
    scene: MyGame,
    plugins: {
        global: [NineSlicePlugin.DefaultCfg],
    },
};

const game = new Phaser.Game(config);

window.addEventListener('resize', function(event) {
    location.reload();
}, false);
